/*
 * Copyright 2003 Program of Computer Graphics, Cornell University
 *     580 Rhodes Hall
 *     Cornell University
 *     Ithaca NY 14853
 * Web: http://www.graphics.cornell.edu/
 * 
 * Not for commercial use. Do not redistribute without permission.
 */
#include "stdafx.h"

#include "PrimitiveList.h"
/*
void intersectPrimitiveLists(PrimitiveList *list, RayExt *ray, IntersectionRecord *hitRec, float cellTMin, float cellTMax)
{
  float tStart = maxv(ray->tStart(),cellTMin);
  float tEnd = minv(ray->tEnd(),cellTMax);
  assert(tStart<=tEnd);
  if (list->func == 0) {
    QuadPackedTriangles *tris = ((QuadPackedTriangleList*)list)->tris;
    for(int count = list->length;count>0;count-=4) {
      //C is e1 X e2
      F32vec4 Cx = tris->e1y*tris->e2z - tris->e1z*tris->e2y;
      F32vec4 Cy = tris->e1z*tris->e2x - tris->e1x*tris->e2z;
      F32vec4 Cz = tris->e1x*tris->e2y - tris->e1y*tris->e2x;
//      F32vec4 denom = F32vec4(1.0f)/(ray->v_dirX*Cx + ray->v_dirY*Cy + ray->v_dirZ*Cz);
      F32vec4 denom = rcp_nr(ray->v_dirX*Cx + ray->v_dirY*Cy + ray->v_dirZ*Cz);
      //S is vertex zero minus the ray origin
      F32vec4 Sx = tris->v0x - ray->v_originX;
      F32vec4 Sy = tris->v0y - ray->v_originY;
      F32vec4 Sz = tris->v0z - ray->v_originZ;
      //t is the parametric parameter along the ray of the intersection
      //t = (S dot C) / (D dot C)
      F32vec4 t = (Sx*Cx + Sy*Cy + Sz*Cz)*denom;
      //B is S X D
      F32vec4 Bx = Sy*ray->v_dirZ - Sz*ray->v_dirY;
      F32vec4 By = Sz*ray->v_dirX - Sx*ray->v_dirZ;
      F32vec4 Bz = Sx*ray->v_dirY - Sy*ray->v_dirX;
      //u is the first barycentric coordinate of the intersection
      //u = (e2 dot B) / (D dot C)
      F32vec4 u = (tris->e2x*Bx + tris->e2y*By + tris->e2z*Bz)*denom;
      //v is the second barycentric coorinate of the intersection
      //v = -(e1 dot B) / (D dot C)
      //we compute negV = -v instead to avoid the extra operation
      F32vec4 negV = (tris->e1x*Bx + tris->e1y*By + tris->e1z*Bz)*denom;
      //test to see if any intersections are valid
      F32vec4 v_zero = _mm_setzero_ps();
      F32vec4 v_one = F32vec4(1.0f);
      F32vec4 valid = cmpge(u,v_zero) & cmple(negV,v_zero) & cmple(u-negV,v_one)
        & cmpgt(t,F32vec4(tStart)) & cmplt(t,F32vec4(tEnd));
      int test = move_mask(valid);
      prefetch(((char *)tris)+256);  //in case we have more triangles in this list
      if (test) { //there is at least one valid intersection
        if (hitRec->func) { //if we have a custom intersection responder, then use it
          int bit = 0x01;
          for(int i=0;i<4;i++) {
            if (test&bit) {
              (*hitRec->func)(ray,hitRec,t[i],u[i],-negV[i],0,tris->id[i]);
            }
            bit = bit+bit;
          }
          tEnd = minv(ray->tEnd(),tEnd); //in case an intersection has shortened the ray
        } else { //otherwise the default is find first intersection
//_asm int 3; //force debugger breakpoint
          int bit = 0x01;
          for(int i=0;i<4;i++) {
            if ((test&bit)&&(t[i]<tEnd)) {
              hitRec->t = ray->tEnd() = tEnd = t[i];
              hitRec->u = u[i];
              hitRec->v = -negV[i];
              hitRec->w = 0.0f;
              hitRec->primitiveId = tris->id[i];
            }
            bit = bit+bit;
          }
        }
      }
      tris++;
    }
    list = list->next;
  }
  while(list!=NULL) {
    (*list->func)(list,ray,hitRec);
  }
}
*/

